package com.logistics.utils.socket;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.google.gson.Gson;
import com.logistics.account.entity.domain.Account;
import com.logistics.account.service.AccountService;
import com.logistics.heart.service.HeartService;
import com.logistics.inventory.service.InventoryService;
import com.logistics.map.service.MapComponentsService;
import com.logistics.socket.model.ResponseSocketModel;
import com.logistics.socket.service.RequestSocketService;
import com.logistics.socket.service.ResponseSocketService;
import com.logistics.utils.exception.MessageException;
import com.logistics.utils.tool.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.math.RandomUtils;
import org.java_websocket.enums.ReadyState;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@ServerEndpoint("/ws/{userId}/{device}")
@Component
public class WebSocketServer {

    private static Gson gson = new Gson();

    private static HeartService heartService;

    private static MapComponentsService mapComponentsService;

    private static InventoryService inventoryService;

    @OnOpen
    public void onOpen(Session session, @PathParam("userId") String userId,
                       @PathParam("device") int device) throws URISyntaxException {
        UserBean userBean = MenConns.userBeans.get(userId);
        if(StringUtils.isNull(userBean)){
            userBean = new UserBean(userId);
        }
        if(device == 0){
            userBean.setPhoneSession(session, device);
            userBean.setIsPhone(true);
        } else {
            userBean.setPcSession(session, device);
            userBean.setIsPhone(false);
        }
        MenConns.userBeans.put(userId, userBean);
        Map<String, Object> userMap = new HashMap<>();
        userMap.put("userId", userId);
        session.getAsyncRemote().sendText(gson.toJson(EventData.build("__login_success", userMap)));
    }

    @OnClose
    public void onClose() {
        log.error("链接关闭");
    }

    @OnMessage
    public void onMessage(String message, Session session) throws JsonProcessingException {
//        System.out.println(message);
        EventData eventData = gson.fromJson(message, EventData.class);
        UserBean userBean = gson.fromJson(eventData.getData().toString(), UserBean.class);
        responseMessage(eventData.getEventName(), userBean.getUserId());
    }

    /**
     * 往前台推送消息
     * @param eventName
     * @param userId
     */
    public void responseMessage(String eventName, String userId){
        switch (eventName){
            case "__heart":
                sendText(userId, "__heart", heartService.hearts());
                break;
            case "__getLocationAndGoods":
                sendText(userId, "__location_goods", mapComponentsService.locationAndGoods());
                break;
            case "__getContainer":
                sendText(userId, "__container", inventoryService.containerPosition());
                break;
            default:
                break;
        }
    }

    /**
     * 发送消息
     * @param userId
     * @param eventName
     * @param object
     */
    void sendText(String userId, String eventName, Object object){
        UserBean userBean = MenConns.userBeans.get(userId);
        if(StringUtils.isNotNull(userBean)){
            try {
                ObjectMapper mapper = new ObjectMapper();
                // 禁用去除null字段的特性
                mapper.disable(SerializationFeature.WRITE_NULL_MAP_VALUES);
                String data = mapper.writeValueAsString(EventData.build(eventName, object));
                if(userBean.getPcSession() != null){
                        userBean.getPcSession().getSession().getAsyncRemote()
                                .sendText(data);
                }else if(userBean.getPhoneSession() != null){
                    userBean.getPhoneSession().getSession().getAsyncRemote()
                            .sendText(data);
                }
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
        }
    }

    @Autowired
    public void setHeartService(HeartService heartService) {
        this.heartService = heartService;
    }

    @Autowired
    public void setMapComponentsService(MapComponentsService mapComponentsService){
        this.mapComponentsService = mapComponentsService;
    }

    @Autowired
    public void setInventoryService(InventoryService inventoryService) {
        this.inventoryService = inventoryService;
    }

}
